package dtrs.corba.server.semaphores;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

import dtrs.corba.server.common.ShowDTO;
import dtrs.corba.utilities.DtrsConstants;


/**
 * management to create file with customeIDand numberOfTickets
 * by showID
 * @author Mary
 *
 */
public class ReserveFile {
	
	private String PATH="c:\\Temp\\DTRS\\";
	
	private File showIDfile;
	ArrayList<String[]> showLine;
	private int operationInFile;
	private String fileName;
	private int customerIdinFile;
	private int numberOfTickets;
	private int numberOfTicketReserved;
	
	  private int signals = 0;
	  private int bound   = 0;
	  
	  

	public ReserveFile(){
		
	}
	
	public ReserveFile(String fileNameP, int customerIdP, int numberTicketsP, int boundP){
		 fileName = fileNameP;
		 customerIdinFile = customerIdP;
		 numberOfTickets = numberTicketsP;
	}
	

	
	public synchronized void getInformationReadWrite(int action, ShowDTO showObj){
		try {
			while(this.signals == bound){
					wait();					
			}
			
			this.signals++;
			notifyAll();
			
			if (action == DtrsConstants.OPERATION_RESERVE){
				this.createFileReserve(fileName, customerIdinFile, numberOfTickets);
			}
			else if (action == DtrsConstants.OPERATION_CANCEL_TICKETS){
				this.updateFileReserve(fileName, customerIdinFile, numberOfTickets);
				
			}else if (action == DtrsConstants.OPERATION_CHECK_TICKETS_DISPO_BY_CUSTOMER){
				this.getTicketsReserved(fileName, customerIdinFile, showObj);
			}
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	public synchronized void releaseFile() {
		try{
			while(this.signals == 0) {
				wait();
			}
		    this.signals--;
		    notifyAll();
		    
	    }catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	  }
	
	/**
	 * Get the quantity of tickets for one client
	 * @param nameFile
	 * @param customerID
	 * @param numberOfTicketsToCancel
	 * @return
	 */
	private void getTicketsReserved(String nameFile, int customerID, ShowDTO showDtoObjP){
		Integer numberOfTicketsReserved = 0;
		try {
				
			showIDfile = new File(PATH+nameFile+".txt");
			if(showIDfile.exists() ){	
				processLineByLine();
				numberOfTicketsReserved = getTicketsCustomerInFile(customerID);
				showDtoObjP.setNumberOfTickets(numberOfTicketsReserved);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} 		
		showDtoObjP.setNumberOfTickets(numberOfTicketsReserved);
	}
	
	/*
	 * to uodate in case of cancel operation
	 */
	private void updateFileReserve(String nameFile,int customerID,
			Integer numberOfTickets){
		try{
			showIDfile = new File(PATH+nameFile+".txt");
			processLineByLine(); 
			if (showLine!=null && showLine.size()>0){
				for(int i=0; i< showLine.size(); i++){
					String[] infoLine = showLine.get(i);
					if (infoLine[0].equals(String.valueOf(customerID))){
						infoLine[1] = String.valueOf((Integer.valueOf(infoLine[1])- numberOfTickets));
						break;
					}
				}
			}
			writeFile();
	    }
		catch(IOException e){
			e.printStackTrace();
		}
	}
		
	private void createFileReserve(String nameFile,int customerID,
			Integer numberOfTickets){
		 try {
			 new File(PATH).mkdir();
		      showIDfile = new File(PATH+nameFile+".txt");

		      if(showIDfile.exists()){ // if exist check if customer has more tickets
		    	  processLineByLine(); 
		    	  
		    	  if (showLine!=null && showLine.size()>0){
		    		  boolean customerIDIsInFile = false;
		    		  for(int i=0; i< showLine.size(); i++){
		    			  String[] infoLine = showLine.get(i);
		    			  if (infoLine[0].equals(String.valueOf(customerID))){
		    				  infoLine[1] = String.valueOf((Integer.valueOf(infoLine[1])+ numberOfTickets));
		    				  customerIDIsInFile = true;
		    				  break;
		    			  }
		    			}
		    		  
		    		   if (!customerIDIsInFile){
		    			  String[] infoLineShow = new String[] {String.valueOf(customerID), String.valueOf(numberOfTickets)}; 
		 			      showLine.add(infoLineShow);
		    		   }
		    	  }
		    	  
		      }
		      else{
		    	  showLine = new ArrayList<String[]>();
		    	  String[] infoLineShow = new String[] {String.valueOf(customerID), String.valueOf(numberOfTickets)}; 
			      showLine.add(infoLineShow);
		      }
		      writeFile();
		    }
	    catch (IOException e) {
	      e.printStackTrace();
	    }
		
	}
		
	private void writeFile(){
		FileWriter fwrite;
		try {
			fwrite = new FileWriter(showIDfile);


			if(showLine !=null && showLine.size()>0){

				for(int j=0; j<showLine.size(); j++){
					String[] infoLine = showLine.get(j); 
					fwrite.write(infoLine[0]+";"+infoLine[1] + "\r"+"\n");
				}		

				fwrite.flush();
				fwrite.close();		    		  
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}


	}
	
	 /** Template method that calls {@link #processLine(String)}.  */
	  private final void processLineByLine() throws FileNotFoundException {
	    //Note that FileReader is used, not File, since File is not Closeable
	    Scanner scanner = new Scanner(showIDfile);
	    showLine = new ArrayList<String[]>();
	    try {
	      //first use a Scanner to get each line
	      while ( scanner.hasNextLine() ){
	        processLine( scanner.nextLine() );
	      }
	    }
	    finally {
	      //ensure the underlying stream is always closed
	      //this only has any effect if the item passed to the Scanner
	      //constructor implements Closeable (which it does in this case).
	      scanner.close();
	    }
	  }
	  
	  /** 
	   Overridable method for processing lines in different ways.
	    
	   <P>This simple default implementation expects simple name-value pairs, separated by an 
	   ';' sign. Examples of valid input : 
	   <tt>customerID;numberOfTickets</tt>
	  */
	  private void processLine(String aLine){
	    //use a second Scanner to parse the content of each line 
		  
		 if (showLine == null){			 
			 showLine = new ArrayList<String[]>();
		 } 
		  
		Scanner scanner = new Scanner(aLine);
	    scanner.useDelimiter(";");
	    if ( scanner.hasNext() ){
	      String customerIdFile = scanner.next();
	      String numberOfTicketsFile = scanner.next();
	      String[] infoLineShow = new String[] {customerIdFile, numberOfTicketsFile}; 
	      showLine.add(infoLineShow);

	    }
	    else {
	     System.out.print("Empty or invalid line. Unable to process.");
	    }
	    //no need to call scanner.close(), since the source is a String
	  }
	  
	  /*
	   * get the tickets for the customer if he is inthe file
	   */
	  private Integer getTicketsCustomerInFile(int customerIdP){		  
		  
			 
		  if (showLine!=null && showLine.size()>0){
	    		 	    		  
	    		  for(int i=0; i< showLine.size(); i++){
	    			  String[] infoLine = showLine.get(i);
	    			  if (infoLine[0].equals(String.valueOf(customerIdP))){
	    				  return Integer.valueOf(infoLine[1]);
	    			  }
	    			}
	    	  }			 
			 return 0;		  
	  }


	public int getOperationInFile() {
		return operationInFile;
	}


	public void setOperationInFile(int operationInFile) {
		this.operationInFile = operationInFile;
	}

	public int getNumberOfTickets() {
		return numberOfTickets;
	}

	public void setNumberOfTickets(int numberOfTickets) {
		this.numberOfTickets = numberOfTickets;
	}


	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public int getCustomerIdinFile() {
		return customerIdinFile;
	}

	public void setCustomerIdinFile(int customerIdinFile) {
		this.customerIdinFile = customerIdinFile;
	}

	public int getSignals() {
		return signals;
	}

	public void setSignals(int signals) {
		this.signals = signals;
	}

	public int getBound() {
		return bound;
	}

	public void setBound(int bound) {
		this.bound = bound;
	}

	public int getNumberOfTicketReserved() {
		return numberOfTicketReserved;
	}

	public void setNumberOfTicketReserved(int numberOfTicketReserved) {
		this.numberOfTicketReserved = numberOfTicketReserved;
	}

	
	  
	  
}
